采用 Org-publish 写博客
本站的内容使用 Emacs 编辑 org-mode 文件,使用 org-publish 导出为 html 文件,布署于 Github 之上。
我的博客源文档放置于私有 Github 仓库中,通过 Github actions 推送到开源的 jousimies.github.io 仓库中。
博客的架构如下:
├── build.el
├── init.el
├── org
│ ├── about.org
│ ├── index.org
│ └── posts
│ ├── 采用 Org-publish 写博客.org
│ └── 我的博客的CSS配置文件.org
└── static
├── js
│ └── main.js
└── style.css
Emacs 中的基本配置 init.el 内容如下:
(require 'ox-publish)
(defvar my/blog-nav-html
"<a href=\"/index.html\">首页</a>
<a href=\"/about.html\">关于</a>"
"博客页面导航栏 HTML 片段。")
(setq org-publish-project-alist
`(
("blog-org"
:base-directory "./org/"
:base-extension "org"
:publishing-directory "./public/"
:recursive t
:html-head "<link rel=\"stylesheet\" href=\"/static/style.css\" />"
:html-head-extra "<script src=\"/static/js/main.js\"></script>"
:html-preamble nil
:html-preamble-format (("en" ,my/blog-nav-html))
:html-postamble t
:html-postamble-format (("en" "<hr><div class=\"info\"> <span class=\"created\">Created with %c on MacOS</span>
<span class=\"updated\">Updated: %d</span> </div>"))
:with-toc t
:section-numbers nil
:with-author nil
:with-creator nil
:with-date t
:publishing-function org-html-publish-to-html
)
("blog-static"
:base-directory "./static/"
:base-extension "css\\|js\\|png\\|jpg\\|svg\\|ico"
:publishing-directory "./public/static/"
:recursive t
:publishing-function org-publish-attachment)
("blog" :components ("blog-org" "blog-static"))))
(defun my/org-blog-update-recent ()
"根据 org 文件更新时间生成 recent.org 文件,用于首页显示最近更新文章列表。"
(interactive)
(let* ((org-dir "./org")
(files (directory-files (expand-file-name "posts" org-dir) t "\\.org$"))
(recent-files
(sort files
(lambda (a b)
(time-less-p (nth 5 (file-attributes b))
(nth 5 (file-attributes a))))))
(top-5 (seq-take recent-files 5)))
(with-temp-file (expand-file-name "recent.org" org-dir)
(insert "* 最近更新\n")
(dolist (f top-5)
(let* ((filename (file-name-nondirectory f))
(title (with-temp-buffer
(insert-file-contents f)
(goto-char (point-min))
(if (re-search-forward "^#\\+TITLE: \\(.*\\)" nil t)
(match-string 1)
filename))))
(insert (format "- [[file:posts\\%s][%s]]\n" filename title)))))))
(defun my/publish-blog ()
"一键发布博客"
(interactive)
(org-publish "blog" t))
build.el 中的内容如下:
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
;; 安装 org 包(如果你依赖 org-plus-contrib,请根据需要改)
(unless (package-installed-p 'org)
(package-install 'org))
(unless (package-installed-p 'htmlize)
(package-install 'htmlize))
;; 加载你的 publish 设置
(load-file "init.el")
;; 执行发布
(org-publish-all t)
(message "Blog published successfully.")
默认导出的 html 文件非常的简单,需要结合 CSS 文件 和 JS 文件,以实现高阶的需求,比如界面的美化、回到上一页、回到首页的功能、侧边栏、动态目录等等。
关于 Github actions 的使用,问 Chatgpt 就好啦,需要注意使用 personal_token 。我的配置如下:
name: Deploy Blog
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Emacs
uses: purcell/setup-emacs@master
with:
version: 30.1
- name: Install Org and dependencies
run: emacs --batch -l build.el
- name: Publish blog
run: emacs --batch -l init.el -f org-publish-all
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
personal_token: ${{ secrets.GH_PAT }}
publish_dir: ./public
external_repository: Jousimies/jousimies.github.io
publish_branch: main